#include <gflags/gflags.h>

#include <memory>
#include <string>
#include <thread>

#include "../../common/channel.h"
#include "../../common/etcd.h"
#include "../../common/log.h"
#include "main.pb.h"

DEFINE_int32(level, 1, "日志等级");
DEFINE_bool(mode, false, "调试模式-false, 发布模式-true");
DEFINE_string(path, "./logfile", "发布模式下日志输出到的文件路径");

DEFINE_string(etcd_host, "http://127.0.0.1:2379", "etcd服务器地址");
DEFINE_string(base_service, "/service", "服务监控根目录");
DEFINE_string(call_service, "/service/echo", "rpc请求目录");

void put_cb(std::string service_name, std::string service_host) {
    LOG_DEBUG("上线服务: {}-{}", service_name, service_host);
}

void del_cb(std::string service_name, std::string service_host) {
    LOG_DEBUG("下线服务: {}-{}", service_name, service_host);
}

int main(int argc, char* argv[]) {
    gflags::ParseCommandLineFlags(&argc, &argv, true);
    initLogger(FLAGS_level, FLAGS_mode, FLAGS_path);

    // 1. 构造 RPC 服务管理对象
    ServiceManagerPtr service_manager = std::make_shared<ServiceManager>();
    service_manager->declared(FLAGS_call_service);  // 添加关心

    // 2. 构造服务发现对象
    auto discovery = std::make_shared<Discovery>(
        FLAGS_etcd_host, FLAGS_base_service,
        std::bind(&ServiceManager::onServiceOnline, service_manager.get(),
                  std::placeholders::_1, std::placeholders::_2),
        std::bind(&ServiceManager::onServiceOffline, service_manager.get(),
                  std::placeholders::_1, std::placeholders::_2));

    while (true) {
        std::this_thread::sleep_for(std::chrono::seconds(2));

        // 3. 通过 RPC 信道管理对象，获取提供 Echo 服务的信道
        ServiceChannel::ChannelPtr channel =
            service_manager->choose(FLAGS_call_service);
        if (channel == nullptr) {
            LOG_ERROR("没有能够提供 {} 的主机", FLAGS_call_service);
            continue;
        }

        // 4. 发起 RPC 调用
        example::EchoService_Stub stub(channel.get());

        example::EchoRequest req;
        example::EchoResponse* resp = new example::EchoResponse;
        req.set_message("hello world!!");

        brpc::Controller* controller = new brpc::Controller;

        stub.Echo(controller, &req, resp, nullptr);  // 同步调用
        if (controller->Failed()) {
            LOG_ERROR("rpc调用失败");
            delete controller;
            delete resp;

            continue;
        }

        LOG_DEBUG("收到响应: {}", resp->message());

        delete controller;
        delete resp;

        break;
    }

    return 0;
}